using System;
using System.Configuration;
using System.Collections;
using System.IO;

using Peradigm.Framework.Configuration;
using Peradigm.Framework.Configuration.Exceptions;
using Peradigm.Framework.Configuration.Messages;
using Peradigm.Framework.Domain.Security;

using Liberty.Domain.CaseManagement;
using Liberty.Domain.GrantManagement;
using Liberty.Domain.NoteManagement;
using Liberty.Domain.ServiceMemberManagement;

namespace Liberty.Application.Security
{
    /// <summary>
    /// Summary description for LibertyApplication.
    /// </summary>
    /// 
    //TODO: Create XML summary comment for LibertyApplication
    [Serializable]
    public class LibertyApplication : Peradigm.Framework.Domain.Security.Application
    {
        #region Constants
        private const string
            CONFIG_CXN_STRING = "ConnectionString",
            CONFIG_APPLICATION_NAME = "ApplicationName",
            CONFIG_APPLICATION_GUID = "ApplicationGUID",
            CONFIG_ACCESS_KEY = "AccessKey";

        public const string
          LIBERTY_USER = "Users",
          LIBERTY_ADMIN = "Admins",
          LIBERTY_GRANT_MANAGER = "GrantManagers",
          LIBERTY_GRANT_APPROVER = "GrantApprovers",
          LIBERTY_FINANCIAL_APPROVER = "FinancialApprovers",
          LIBERTY_FUND_MANAGER = "FundManagers";

        #endregion

        #region Event Handlers
        #endregion

        #region Methods
        #endregion

        #region Properties
        #endregion

        #region Private Methods
        private void InitializeRoles()
        {
            this.DefineRoles();
            this.DefineRoleHeirarchy();
        }

        private void DefineRoles()
        {
            this.AddRole( this.BuildLibertyUserRole() );
            this.AddRole( this.BuildLibertyGrantManagerRole() );
            this.AddRole( this.BuildLibertyGrantApproverRole() );
            this.AddRole( this.BuildLibertyFinancialApproverRole() );
            this.AddRole( this.BuildLibertyFundManagerRole() );
            this.AddRole( new Role( LibertyApplication.LIBERTY_ADMIN ) );
        }

        private void DefineRoleHeirarchy()
        {
            Role adminRole = this.RoleWith( LibertyApplication.LIBERTY_ADMIN ),
                financialApproverRole = this.RoleWith( LibertyApplication.LIBERTY_FINANCIAL_APPROVER ),
                grantApproverRole = this.RoleWith( LibertyApplication.LIBERTY_GRANT_APPROVER ),
                grantManagerRole = this.RoleWith( LibertyApplication.LIBERTY_GRANT_MANAGER ),
                fundManagerRole = this.RoleWith( LibertyApplication.LIBERTY_FUND_MANAGER ),
                userRole = this.RoleWith( LibertyApplication.LIBERTY_USER );

            userRole.AddMember( grantManagerRole );
            
            grantManagerRole.AddMember( grantApproverRole );
            grantManagerRole.AddMember( financialApproverRole );
            grantManagerRole.AddMember( fundManagerRole );

            grantApproverRole.AddMember( adminRole );
            
            financialApproverRole.AddMember( adminRole );

            fundManagerRole.AddMember( adminRole );
        }

        private Role BuildLibertyUserRole()
        {
            Role role = new Role( LibertyApplication.LIBERTY_USER );
            role.AddPrivilege( new ViewGrantPrivilege( ViewGrantPrivilege.Actions.View, null ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.View, typeof( Case ) ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.View, typeof( ServiceMember ) ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.View, typeof( Note ) ) );
            return role;
        }

        private Role BuildLibertyGrantManagerRole()
        {
            Role role = new Role( LibertyApplication.LIBERTY_GRANT_MANAGER );
            role.AddPrivilege( new Privilege( Privilege.Actions.Add, typeof( Grant ) ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.Edit, typeof( Grant ) ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.Remove, typeof( Grant ) ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.Add, typeof( Case ) ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.Edit, typeof( Case ) ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.Remove, typeof( Case ) ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.Add, typeof( ServiceMember ) ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.Edit, typeof( ServiceMember ) ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.Remove, typeof( ServiceMember ) ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.Add, typeof( Note ) ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.Edit, typeof( Note ) ) );
            role.AddPrivilege( new Privilege( Privilege.Actions.Remove, typeof( Note ) ) );
            return role;
        }

        private Role BuildLibertyGrantApproverRole()
        {
            Role role = new Role( LibertyApplication.LIBERTY_GRANT_APPROVER );
            role.AddPrivilege( new Privilege( Privilege.Actions.View, typeof( Grant ) ) );
            role.AddPrivilege( new ApproveGrantPrivilege( Privilege.Actions.Approve, null ) );
            return role;
        }

        private Role BuildLibertyFinancialApproverRole()
        {
            Role role = new Role( LibertyApplication.LIBERTY_FINANCIAL_APPROVER );
            role.AddPrivilege( new Privilege( Privilege.Actions.View, typeof( Grant ) ) );
            role.AddPrivilege( new DisperseGrantPrivilege( Privilege.Actions.Approve, null ) );
            return role;
        }

        private Role BuildLibertyFundManagerRole()
        {
            Role role = new Role( LibertyApplication.LIBERTY_FUND_MANAGER );
            role.AddPrivilege( new Privilege( Privilege.Actions.View, typeof( Grant ) ) );
            role.AddPrivilege( new ApproveGrantPrivilege( Privilege.Actions.Approve, null ) );
            return role;
        }
        #endregion

        #region Private Properties
        private string ConnectionString
        {
            get
            {
                string setting = ApplicationConfiguration.Settings[CONFIG_CXN_STRING];
                if( setting == null || setting.Trim() == String.Empty )
                {
                    throw new SettingIsNotAvailableException( CONFIG_CXN_STRING );
                }
                return setting;
            }
        }
        #endregion

        #region Construction and Finalization

        public LibertyApplication()
            : this( ApplicationConfiguration.Settings[CONFIG_APPLICATION_NAME], String.Empty, String.Empty, String.Empty )
        {
        }

        public LibertyApplication( string appName, string environment, string buildVersion,
                                 string serverName )
            : base( ApplicationConfiguration.Settings[CONFIG_ACCESS_KEY],
                    ApplicationConfiguration.Settings[CONFIG_APPLICATION_GUID],
                    appName,
                    environment, buildVersion, serverName )
        {
            this.InitializeRoles();
        }
        #endregion

        #region Data Elements
        #endregion
    }
}